﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net;
using System.IO;
using System.Xml;
using System.Threading;
using System.Globalization;

namespace VKontakteClient
{
    /// <summary>
    /// Логика контрола Логина
    /// </summary>
    public partial class LogOnControl : UserControl
    {
        /// <summary>
        /// Конструктор
        /// </summary>
        public LogOnControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Переменная, хранящая показывать ли капчу
        /// </summary>
        [Obsolete]
        private bool _showCaptcha;

        /// <summary>
        /// Свойство, хранящее показывать ли капчу
        /// </summary>
        [Obsolete]
        private bool ShowCaptcha
        {
            get
            {
                return _showCaptcha;
            }
            set
            {
                if (_showCaptcha == value) return;
                if (_showCaptcha == true) return;
                _showCaptcha = true;
                CaptchaStack.Visibility = Visibility.Visible;
                CaptchaImg.Visibility = Visibility.Visible;
            }
        }

        /// <summary>
        /// Блокирнуть ли форму
        /// </summary>
        private bool Lock
        {
            set
            {
                Pass.IsEnabled = !value;
                EMail.IsEnabled = !value;
                Captcha.IsEnabled = !value;
                AuthorizeButton.IsEnabled = !value;
                AuthorizeButton1.IsEnabled = !value;
                AuthorizeButton2.IsEnabled = !value;
            }
        }

        /// <summary>
        /// Проверка возможности логина по кукам
        /// </summary>
        /// <returns>True если успешный логин</returns>
        private static bool CheckLogin()
        {
            var Converted = VKontakteAPI.GetPage("profile.php",2);
            if (Converted.IndexOf("<div id='error'>", StringComparison.CurrentCulture) > 0)
            {
                return false;
            }
            if (Converted.IndexOf("<div id='message'>", StringComparison.CurrentCulture) > 0)
            {
                return false;
            }
            if (Converted.StartsWith("Ошибка")) return false;
            Converted = Converted.Remove(Converted.IndexOf("Моя Страница", StringComparison.CurrentCulture));
            Converted = Converted.Remove(0, Converted.LastIndexOf("<a href='id", StringComparison.CurrentCulture));
            Converted = Converted.Substring(Converted.IndexOf("id", StringComparison.CurrentCulture), Converted.IndexOf("?", StringComparison.CurrentCulture) - Converted.IndexOf("id", StringComparison.CurrentCulture));
            Converted = Converted.Remove(0, 2);
            if (App.Settings.Myself == null)
            {
                int i = int.Parse(Converted, CultureInfo.InvariantCulture);
                App.Settings.Myself = Human.GetHuman(i);
            }
            return true;
        }

        /// <summary>
        /// Вход в систему по логину и паролю.
        /// </summary>
        /// <param name="Username">Имя пользователя(email) для входа</param>
        /// <param name="Password">Пароль пользователя</param>
        /// <returns>Возвращает (string)текст ошибки, или (boolean)true при успешном входе</returns>
        private static object Login(string Username, string Password)
        {
            object result = null;
            byte[] data = new ASCIIEncoding().GetBytes("op=a_login_attempt&email=" + Username + "&pass=" + Password+"&expire=0");
            var wr = VKontakteAPI.GetWebRequest("login.php", data);
            var res = (HttpWebResponse)wr.GetResponse();
            result = VKontakteAPI.GetResponse(res, false);
            if (result.ToString() == "failed")
            {
                return "Ошибка входа.";
            }
            else
            {
                var X = res.GetResponseHeader("Set-Cookie").Split(',').Where(v => v.Contains("expires")).Select(v => new Cookie(v.Remove(v.IndexOf('=')), v.Substring(v.IndexOf('=') + 1, v.IndexOf(';') - v.IndexOf('=') - 1)));
                foreach (var v in X)
                    App.Settings.Cookies.Add(v);
                int ID = int.Parse(((string)result).Replace("good", ""), CultureInfo.InvariantCulture);
                App.Settings.Myself = Human.GetHuman(ID);
                result = true;
            }
            res.Close();
            return result;
        }

        /// <summary>
        /// Метод нажатия на кнопку логина
        /// </summary>
        private void Authorize(object sender, RoutedEventArgs e)
        {
            Lock = true;
            App.Settings.Password = Pass.Password;
            App.Settings.LogOnName = EMail.Text;
            SynchronizationContext sc = SynchronizationContext.Current;
            App.Scheduler.Enqueue(
                () =>
                {
                    bool NotLoaded = true;
                    object X = null;
                    for (int i = 0; i < 5 && NotLoaded; i++)
                    {
                        NotLoaded = false;
                        try
                        {
                            X = Login(App.Settings.LogOnName, App.Settings.Password);
                        }
                        catch
                        {
                            NotLoaded = true;
                        }
                    }
                    sc.Post((object o) =>
                    {
                        if (X is string || NotLoaded)
                        {
                            Message.Content = X;
                        }
                        else
                        {
                            this.Visibility = Visibility.Collapsed;
                            App.IsOffline = false;
                            AuthorizeCaller();
                        }
                        Lock = false;
                    }, null);
                }, ThreadPriority.Highest, () => { return "Вход в ВКонтакте через имя/пароль..."; });
        }

        /// <summary>
        /// Метод вызываемый при окончании инициализации контрола логина. 
        /// </summary>
        private void LoginControl_Loaded(object sender, RoutedEventArgs e)
        {
                Pass.Password = App.Settings.Password;
                EMail.Text = App.Settings.LogOnName;
        }

        /// <summary>
        /// Событие которое дергается при успешном входе
        /// </summary>
        public event EventHandler Authorized;

        /// <summary>
        /// Вызывает проверку логина по кукам.
        /// </summary>
        private void AuthorizeButton1_Click(object sender, RoutedEventArgs e)
        {
            if ((App.Settings.Cookies["remixsid"] != null) && (App.Settings.Cookies["remixpass"] != null) && (App.Settings.Cookies["remixemail"] != null))
            {
                Lock = true;
                App.Scheduler.Enqueue(
                    () =>
                    {
                        if (CheckLogin())
                        {
                            App.IsOffline = false;
                            AuthorizeCaller();
                        }
                        else
                        {
                            MessageBox.Show("Ошибка входа!");
                        }
                        Lock = false;
                    }, ThreadPriority.Highest, () => { return "D["; });
            }
        }

        /// <summary>
        /// Метод дергания события успешной авторизация
        /// </summary>
        private void AuthorizeCaller()
        {
            AuthorizeCaller(true);
        }

        /// <summary>
        /// Метод дергания события успешной авторизация
        /// </summary>
        /// <param name="SaveCookies">Сохранить ли куки в IE</param>
        private void AuthorizeCaller(bool SaveCookies)
        {
            if (Authorized != null)
                Authorized(this, null);
            if (SaveCookies) foreach (Cookie v in App.Settings.Cookies)
                VKontakteAPI.SetCookie(v);
        }

        /// <summary>
        /// Оффлайн-вход
        /// </summary>
        private void AuthorizeButton2_Click(object sender, RoutedEventArgs e)
        {
            App.IsOffline = true;
            if (App.Settings.Myself == null)
            {
                MessageBox.Show("Вы ни разу не входили в ВКонтакте в онлайн-режиме. Работа в оффлайне не возможна.");
                return;
            }
            AuthorizeCaller(false);
        }
    }
}
